;;;; Copyright 2009 Peter von Etter

;;;; This file is part of Autoproject

;;;; Autoproject is free software: you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation, either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; Autoproject is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with Autoproject.  If not, see
;;;; <http://www.gnu.org/licenses/>.

(in-package :autoproject)

(labels ((make-save-core-form (core-name)
           `(save-lisp-and-die ,core-name))
         
         (asdf-file-location (system)
           (truename (asdf:system-definition-pathname system)))

         (resolve-system (system)
           (typecase system
             (pathname
              (string-downcase (pathname-name system)))
             (string
              (string-downcase (pathname-name (pathname system))))
             (symbol
              (string-downcase system)))))

  #+nil
  (defun execute-make-for-system (system target)
    (let ((pathname (asdf-file-location (resolve-system system))))
      (run-program "make" (list "-C" (directory-namestring pathname)
                                target))))

  (defun make-makefile-for-system (system-name)
    (let* ((system-name (resolve-system system-name))

           (base-core-name (format nil "~A.base.core" system-name))

           (core-name (format nil "~A.core" system-name))

           (asdf-file-location (asdf-file-location system-name))

           #+nil
           (object-dir (directory-namestring asdf-file-location)) 

           (makefile-pathname
            (merge-pathnames (make-pathname :name "Makefile"
                                            :type "ap")
                             (pathname (directory-namestring
                                        asdf-file-location))))
           
           (base-core-var "$(BASE_CORE)")

           (core-var "$(CORE)")
           
           (build-target
            (make-lisp-shell-command 
             :batch t
             :core base-core-var
             :eval `((require ,system-name)
                     (quit))))

           (build-no-base-target
            (make-lisp-shell-command 
             :batch t
             :eval `((require ,system-name)
                     (quit))))

           (rebuild-target
            (make-lisp-shell-command 
             :batch t
             :core base-core-var
             :eval `((recompile-asdf-system ,system-name)
                     (quit))))

           (build-incremental-target
            (make-lisp-shell-command 
             :batch t
             :eval `((require ,*this-package*)
                     (compile-asdf-system-incrementally ,system-name)
                     (quit))))

           (rebuild-incremental-target
            (make-lisp-shell-command 
             :batch t
             :eval `((require ,*this-package*)
                     (recompile-asdf-system-incrementally ,system-name)
                     (quit))))

           (base-core-target
            (make-lisp-shell-command 
             :batch t
             :eval `((require ,*this-package*)
                     (load-asdf-system-dependencies ,system-name)
                     ,(make-save-core-form base-core-var))))
           
           (core-target 
            (make-lisp-shell-command 
             :core base-core-var
             :batch t
             :eval `((require ,system-name)
                     ,(make-save-core-form core-var)))) 

           (clean-target
            (format nil "~A
	-rm ~A ~A"
                    (make-lisp-shell-command 
                     ;; :core base-core-name
                     :batch t
                     :eval `((require ,*this-package*)
                             (asdf:oos 'asdfa:revert-op ,system-name)
                             (quit)))
                    base-core-var
                    core-var))                    
             
           (slime-target
            (make-lisp-shell-command 
             :core base-core-name
             :eval `((require ,system-name)
                     (require :swank)
                     (funcall (read-from-string "SWANK::CREATE-SERVER")))))

           (run-target
            (make-lisp-shell-command 
             :core core-var))

           (makefile-contents
            (format nil
                    "# This file was auto-generated

BASE_CORE = ~A
CORE = ~A

all: build

build: ~A
	~A

rebuild: ~A
	~A

build-inc: 
	~A

rebuild-inc: 
	~A

baseless:
	~A

~A:
	~A

~A: ~A
	~A

run: ~A
	~A

slime: ~A
	~A

base-core: ~A

core: ~A

clean:
	~A


.PHONY: build core base-core clean
"
                    ;; Vars
                    base-core-name
                    core-name
                    
                    ;; Build
                    base-core-var
                    build-target
                    
                    ;; Rebuild
                    base-core-var
                    rebuild-target

                    ;; Incremental build
                    build-incremental-target

                    ;; Incremental rebuild
                    rebuild-incremental-target

                    ;; Build no base
                    build-no-base-target

                    ;; Base core
                    base-core-var
                    base-core-target

                    ;; Core
                    core-var
                    base-core-var
                    core-target

                    ;; Run
                    core-var
                    run-target
                    
                    ;; Slime
                    base-core-var
                    slime-target

                    ;; Base core alias
                    base-core-var
                    
                    ;; Core alias
                    core-var
                    
                    ;; Clean
                    clean-target)))      
      
      (with-open-file (s makefile-pathname
                         :direction :output
                         :if-exists :supersede)
        (princ makefile-contents s)))))

